package com.me.extend.toast

import android.content.Context
import android.content.ContextWrapper
import android.os.Build
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.widget.Toast
import androidx.annotation.StringRes
import androidx.fragment.app.Fragment
import com.me.extend.ctx.appCtx
import com.me.extend.log.logE
import com.me.extend.resources.txt
import com.me.extend.services.layoutInflater
import com.me.extend.services.windowManager

private class SafeToastCtx(ctx: Context) : ContextWrapper(ctx) {

    private val toastWindowManager by lazy(LazyThreadSafetyMode.NONE) {
        ToastWindowManager(
            baseContext.windowManager
        )
    }
    private val toastLayoutInflater by lazy(LazyThreadSafetyMode.NONE) {
        baseContext.layoutInflater.cloneInContext(this)
    }

    override fun getApplicationContext(): Context = SafeToastCtx(baseContext.applicationContext)

    override fun getSystemService(name: String): Any = when (name) {
        Context.LAYOUT_INFLATER_SERVICE -> toastLayoutInflater
        Context.WINDOW_SERVICE -> toastWindowManager
        else -> super.getSystemService(name)
    }

    private class ToastWindowManager(private val base: WindowManager) : WindowManager by base {
        override fun addView(view: View?, params: ViewGroup.LayoutParams?) {
            try {
                base.addView(view, params)
            } catch (e: Exception) {
                "不能添加Toast到WindowManager".logE(throwable = e)
            }
        }
    }
}

@PublishedApi
internal fun Context.createToast(text: CharSequence, duration: Int): Toast {
    val ctx = if (Build.VERSION.SDK_INT == 25) SafeToastCtx(this) else this
    return Toast.makeText(ctx, text, duration)
}

@PublishedApi
internal fun Context.createToast(@StringRes resId: Int, duration: Int): Toast {
    return createToast(txt(resId), duration)
}

@PublishedApi
internal val Fragment.ctx: Context
    get() = context ?: appCtx

fun Context.toast(@StringRes msgResId: Int) = createToast(msgResId, Toast.LENGTH_SHORT).show()
fun Fragment.toast(@StringRes msgResId: Int) = ctx.toast(msgResId)
fun View.toast(@StringRes msgResId: Int) = context.toast(msgResId)
fun toast(@StringRes msgResId: Int) = appCtx.toast(msgResId)

fun Context.toast(msg: CharSequence) = createToast(msg, Toast.LENGTH_SHORT).show()
fun Fragment.toast(msg: CharSequence) = ctx.toast(msg)
fun View.toast(msg: CharSequence) = context.toast(msg)
fun toast(msg: CharSequence) = appCtx.toast(msg)
fun String.toast() = toast(this)

fun Context.longToast(@StringRes msgResId: Int) = createToast(msgResId, Toast.LENGTH_LONG).show()
fun Fragment.longToast(@StringRes msgResId: Int) = ctx.longToast(msgResId)
fun View.longToast(@StringRes msgResId: Int) = context.longToast(msgResId)
fun longToast(@StringRes msgResId: Int) = appCtx.longToast(msgResId)

fun Context.longToast(msg: CharSequence) = createToast(msg, Toast.LENGTH_LONG).show()
fun Fragment.longToast(msg: CharSequence) = ctx.longToast(msg)
fun View.longToast(msg: CharSequence) = context.longToast(msg)
fun longToast(msg: CharSequence) = appCtx.longToast(msg)
fun String.longToast() = longToast(this)